using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using AllInOnePluginBL.FileHostingExtractors;
using NLog;
using PluginDB;

namespace AllInOnePluginBL.Helpers
{
    /// <summary>
    /// Summary description for Utils
    /// </summary>
    public class Utils
    {
        private static readonly Logger _log = LogManager.GetLogger("Utils");
        private static readonly List<IFileHostingExtractor> fileHostingExtractors = new List<IFileHostingExtractor>
                                            {
                                                new MytubeExtractor(),
                                                //new MegaUploadExtractor(),
                                                //new MegaVideoExtractor(),
                                                //new MultiUploadExtractor(),
                                                new ModovideoExtractor(),
                                                new SdarotOrgExtractor(),
                                                new CuevanaTVExtractor(),
                                                //new VideoBBExtractor(),
                                                //new VideozerExtractor()
                                                new VideoweedExtractor()
                                            };

        public static string LoopDecodeUrl(string baseUrl)
        {
            const int MAX_RETRIES = 5;
            int retries = 0;
            do
            {
                baseUrl = HttpUtility.UrlDecode(baseUrl);
                retries++;
            } while (baseUrl.Contains("%") && retries < MAX_RETRIES);

            return baseUrl;
        }

        public static string DecodeUrl(string url)
        {
            try
            {
                var decodeUrl = LoopDecodeUrl(url);
                var urlByts = Convert.FromBase64String(decodeUrl);
                return LoopDecodeUrl(Encoding.Default.GetString(urlByts));
            }
            catch
            {
                return url;
            }
        }

        public static string EncodeUrl(string url)
        {
            var encodedUrl = HttpUtility.UrlEncode(url);
            if (encodedUrl != null)
            {
                var urlByts = Encoding.Default.GetBytes(encodedUrl);
                return HttpUtility.UrlEncode(Convert.ToBase64String(urlByts));
            }
            throw new Exception("url is empty");
        }

        public static string GetSiteUrl()
        {
            if (HttpContext.Current.Request.Url.OriginalString.IndexOf("?") != -1)
                return HttpContext.Current.Request.Url.OriginalString.Substring(0, HttpContext.Current.Request.Url.OriginalString.IndexOf("?"));
            return HttpContext.Current.Request.Url.OriginalString;
        }

        public static string GetParam(NameValueCollection queryStringParams, string name, string defaultValue)
        {
            return queryStringParams[name] ?? defaultValue;
        }

        public static int GetParam(NameValueCollection queryStringParams, string name, int defaultValue)
        {
            return int.Parse(GetParam(queryStringParams, name, defaultValue.ToString()));
        }

        public static string GetPage(string url, Encoding encoding)
        {
            return GetPage(url, encoding, string.Empty, string.Empty, null, null);
        }

        public static string GetPage(string url, Encoding encoding, Uri cookieUrl, Cookie cookie)
        {
            return GetPage(url, encoding, string.Empty, string.Empty, cookieUrl, cookie);
        }

        public static string GetPage(string url, Encoding encoding, string referer, string postParameters)
        {
            return GetPage(url, encoding, referer, postParameters, null, null);
        }        

        public static string GetPageCookiesString(string url)
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Headers.Add("UserAgent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3");
            
            WebResponse response = null;
            try
            {
                response = request.GetResponse();
                response.GetResponseStream();
                return response.Headers["set-cookie"];
            }
            finally
            {
                if (response != null)
                    response.Close();
            }
        }

        public static string GetMegaUploadMovieUrlContent(string url, Encoding encoding, string cookieHeader, out bool isStream)
        {
            //"application/octet-stream"
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Headers.Add("UserAgent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3");
            request.Headers.Add("Cookie", cookieHeader);

            isStream = false;
            WebResponse response = null;
            Stream stream = null;
            StreamReader reader = null;
            const int retries = 2;
            var count = 0;
            while (count < retries)
            {
                try
                {
                    response = request.GetResponse();
                    stream = response.GetResponseStream();

                    if (!response.ContentType.ToLower().StartsWith("text/"))
                    {
                        isStream = true;
                        return response.ResponseUri.ToString();
                    }

                    string buffer = "", line;

                    reader = new StreamReader(stream, encoding);

                    while ((line = reader.ReadLine()) != null)
                    {
                        buffer += line + "\r\n";
                    }

                    return buffer;
                }
                catch
                {
                    count++;
                    Thread.Sleep(1000);
                }
                finally
                {
                    if (reader != null)
                        reader.Close();

                    if (stream != null)
                        stream.Close();

                    if (response != null)
                        response.Close();
                }
            }

            throw new Exception("The Requested url is not reposnding. Try again later");
        }
        public static string GetPageWithCookieHeader(string url, Encoding encoding, string cookieHeader)
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Headers.Add("UserAgent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3");
            request.Headers.Add("Cookie", cookieHeader);

            return GetPage(request, encoding);
        }

        public static string GetPage(string url, Encoding encoding, string referer, string postParameters, Uri cookieUrl, Cookie cookie)
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Headers.Add(HttpRequestHeader.AcceptLanguage, "en");
            request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3";

            if (cookie != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookieUrl, cookie);
            }

            if(!string.IsNullOrEmpty(referer))
                request.Referer = referer;

            if(!string.IsNullOrEmpty(postParameters))
            {
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                var bytes = Encoding.ASCII.GetBytes(postParameters);
                request.ContentLength = bytes.Length;
                var os = request.GetRequestStream();
                os.Write(bytes, 0, bytes.Length);
            }

            return GetPage(request, encoding);
        }

        public static string GetMegaVideoPremium()
        {
            try
            {
                const string MEGAVIDEO_NAME = "MegaVideo";

                var cacheCookie = CacheManager.Instance.GetData("MegaVideoCookie") as FileHostingCooky;
                if (cacheCookie != null) return cacheCookie.CookieValue;

                var pluginDBHandler = PluginDBHandler.Instance;
                var cookie = pluginDBHandler.GetCookieCode(MEGAVIDEO_NAME);

                if (cookie == null || !MegaVideoExtractor.IsPremiumMegaVideoUser(cookie.CookieValue))
                {
                    var pageCookie = CreateMegaVideoCookieID("kachupi", "danar");
                    if (pageCookie == null) throw new Exception("Failed to create cookie for user");

                    pluginDBHandler.InsertNewCookieCode(pageCookie.Value, pageCookie.Expires, MEGAVIDEO_NAME);
                    cookie = pluginDBHandler.GetCookieCode(MEGAVIDEO_NAME);
                }

                if (cookie == null || cookie.Expired == null)
                    throw new Exception("GetMegaVideoPremium didnt find any cookie");

                CacheManager.Instance.CacheData("MegaVideoCookie", cookie, cookie.Expired.Value);
                return cookie.CookieValue;
            }
            catch(Exception ex)
            {
                _log.ErrorException("Error white trying to save megaupload cookie.", ex);
                return string.Empty;
            }
        }

        public static List<string> GetMovieLinks(string pageContent)
        {
            var movieLinks = new List<string>();

            foreach (var fileHostingExtractor in
                fileHostingExtractors.Where(fileHostingExtractor => fileHostingExtractor.IsContainVideoLink(pageContent)))
            {
                movieLinks.AddRange(fileHostingExtractor.GetMovieUrls(pageContent));
            }
            return movieLinks;
        }
        
        public static String ConstructQueryString(NameValueCollection parameters)
        {
            return String.Join("&", (from string name in parameters
                                     select String.Concat(name, "=", HttpUtility.UrlEncode(parameters[name]))).ToArray());
        }

        public static bool IsBrokenLink(string url, out string errorText)
        {
            try
            {
                errorText = string.Empty;
                var videoResult = ExtractVideoFullLink(url);
                return (videoResult == null || !videoResult.IsValid);
            }
            catch (Exception ex)
            {
                errorText = ex.Message;
                return true;
            }
        }

        public static bool IsBrokenLink(string url)
        {
            try
            {
                var videoResult = ExtractVideoFullLink(url);
                return (videoResult == null || !videoResult.IsValid);

                //var http = (HttpWebRequest)WebRequest.Create(url);
                //http.UserAgent = "Mozilla/9.0 (compatible; MSIE 6.0; Windows 98)";
                //http.Method = "HEAD";
                //http.Timeout = 10000;
                //var httpresponse = (HttpWebResponse)http.GetResponse();

                //return httpresponse.StatusCode != HttpStatusCode.OK;
            }
            catch (Exception)
            {
                return true;
            }
        }

        public static bool IsContainsHebrew(IEnumerable<char> text)
        {
            const int hebrewMinValue = 0x0590;
            const int hebrewMaxValue = 0x05FF;

            return text.Any(myChar => (myChar >= hebrewMinValue) && (myChar <= hebrewMaxValue));
        }       

        public static string CleanHtmlContent(string str)
        {
            str = str.Replace("\r", string.Empty);
            str = str.Replace("\n", string.Empty);
            str = str.Replace("\t", string.Empty);
            return str;
        }

        public static string HtmlDecodeUrl(string htmlText)
        {
            return HttpUtility.HtmlDecode(htmlText);
        }

        public static VideoResult ExtractVideoFullLink(string url)
        {
            return fileHostingExtractors
                .Where(fileHostingExtractor => fileHostingExtractor.IsContainVideoLink(url))
                .Select(fileHostingExtractor => fileHostingExtractor.ExtractMovieUrl(url))
                .FirstOrDefault();
        }

        public static string GetCookieString(string url)
        {
            var newCookieBuilder = new StringBuilder();
            var cookieString = GetPageCookiesString(url);
            var firstSplit = cookieString.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in firstSplit)
            {
                var subItem = item.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
                newCookieBuilder.AppendFormat("{0};", subItem[0]);
            }

            return newCookieBuilder.ToString();
        }

        public static bool isEmail(string inputEmail)
        {
            const string strRegex = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                                    @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                                    @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
            var re = new Regex(strRegex);
            return re.IsMatch(inputEmail);
        }

        #region Private Methods
        private static string GetPage(HttpWebRequest request, Encoding encoding)
        {
            WebResponse response = null;
            Stream stream = null;
            StreamReader reader = null;
            const int retries = 2;
            var count = 0;
            while (count < retries)
            {
                try
                {
                    if (request.UserAgent == null)
                        request.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7";
                    
                    response = request.GetResponse();
                    stream = response.GetResponseStream();

                    if (!response.ContentType.ToLower().StartsWith("text/"))
                        return null;

                    string buffer = "", line;

                    reader = new StreamReader(stream, encoding);
                    return reader.ReadToEnd();
                    //while ((line = reader.ReadLine()) != null)
                    //{
                    //    buffer += line + "\r\n";
                    //}

                    //return buffer;
                }
                catch
                {
                    count++;
                    Thread.Sleep(1000);
                }
                finally
                {
                    if (reader != null)
                        reader.Close();

                    if (stream != null)
                        stream.Close();

                    if (response != null)
                        response.Close();
                }
            }

            throw new Exception("The Requested url is not reposnding. Try again later");
        }

        private static Cookie CreateMegaVideoCookieID(string userName, string password)
        {
            HttpWebResponse response = null;
            Stream stream = null;
            StreamReader reader = null;
            const int retries = 2;
            var count = 0;
            while (count < retries)
            {
                try
                {
                    const string url = "http://www.megavideo.com/?c=login";
                    var paramaters = string.Format("login=1&redir=1&username={0}&password={1}", userName, password);
                    var request = (HttpWebRequest)WebRequest.Create(url);
                    request.CookieContainer = new CookieContainer();
                    request.Method = "POST";
                    request.ContentType = "application/x-www-form-urlencoded";

                    var bytes = Encoding.ASCII.GetBytes(paramaters);
                    request.ContentLength = bytes.Length;
                    var os = request.GetRequestStream();
                    os.Write(bytes, 0, bytes.Length);

                    request.Headers.Add("UserAgent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3");
                    request.Referer = "http://www.megavideo.com/?s=signup";

                    response = (HttpWebResponse)request.GetResponse();
                    response.Cookies = request.CookieContainer.GetCookies(request.RequestUri);
                    stream = response.GetResponseStream();

                    string buffer = "", line;

                    reader = new StreamReader(stream);

                    while ((line = reader.ReadLine()) != null)
                    {
                        buffer += line + "\r\n";
                    }

                    if (buffer.ToLower().Contains(userName.ToLower()))
                    {
                        var cookie = response.Cookies[0];
                        return cookie;
                    }
                }
                finally
                {
                    if (reader != null)
                        reader.Close();

                    if (stream != null)
                        stream.Close();

                    if (response != null)
                        response.Close();
                }
                count++;
            }

            return null;
        } 
        #endregion
    }
}